package com.fh.common.concurrent;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.ForkJoinTask;
import java.util.concurrent.RecursiveAction;

/**
 * @Author qiujunda
 * @Date 16/07/2020
 * @Description
 */
public class ListRecursiveAction<T> extends RecursiveAction {
    private List<T> taskList;
    private int start;
    private int end;
    private ListTask<T> listTask;
    private static final int THRESHOLD = 20;

    public void setListTask(ListTask<T> listTask) {
        this.listTask = listTask;
    }
    public static ListRecursiveAction buildListRecursiveAction(List taskList,int start,int end){
        ListRecursiveAction listRecursiveAction=new ListRecursiveAction();
        listRecursiveAction.taskList=taskList;
        listRecursiveAction.start=start;
        listRecursiveAction.end=end;
        return listRecursiveAction;
    }

    public static ListRecursiveAction buildListRecursiveAction(List taskList,int start,int end,ListTask listTask){
        ListRecursiveAction listRecursiveAction=new ListRecursiveAction();
        listRecursiveAction.taskList=taskList;
        listRecursiveAction.start=start;
        listRecursiveAction.end=end;
        listRecursiveAction.listTask=listTask;
        return listRecursiveAction;
    }

    public void run(){
        compute();
    }


    @Override
    protected void compute() {
        if (end-start > THRESHOLD) {
            ForkJoinTask.invokeAll(createSubtasks());
        } else {
            processing();
        }
    }

    private List<ListRecursiveAction> createSubtasks() {
        List<ListRecursiveAction> subtasks = new ArrayList<>();
        int middle = (end-start)/2+start;
        subtasks.add(ListRecursiveAction.buildListRecursiveAction(this.taskList,start,middle,this.listTask));
        subtasks.add(ListRecursiveAction.buildListRecursiveAction(this.taskList,middle,end,this.listTask));
        return subtasks;
    }

    private void processing() {
        for(int i=this.start;i<this.end;i++){
            T t=this.taskList.get(i);
            listTask.run(t);
        }
    }

    public static void main(String[] args) {
        List<String> l= Arrays.asList("1","2","3","4","5","6","7");
        ListRecursiveAction <String> action = ListRecursiveAction.buildListRecursiveAction(l,0,l.size(),(str)->{
            System.out.println(Thread.currentThread().getId()+"---"+str);
        });
        action.compute();
        System.out.println("------------123");
    }
}
